#include "mainwindow.h"
#include <QFileDialog>
#include "./ui_mainwindow.h"
#include "detectiondialog.h"
#include "dahengcamera.h"
#include "seatdao.h"
#include "selfcheckingthread.h"
#include "waitdialog.h"

MainWindow* MainWindow::_instance = nullptr;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_pTimer(nullptr)
    , m_pTcpPLCClient(nullptr)
    , m_pTcpRecognizeClient(nullptr)
    , m_pSeatParameterDialog(nullptr)
    , m_pDetectionDialog(nullptr)
    , m_nTrayCount(0)
    , m_nSeatCount(0)
    , m_nDetectionCount(0)
    , m_nDefectSeatCount(0)
    , m_nDefectCount(0)
    , m_bHasSomeClosed(TRUE)
{
    ui->setupUi(this);

    // 打开日志处理器
#ifdef USE_LOGGING
    InitLog();
#endif

    InitCameraLib();

    InitParameterFromXMLFile(QString("SeatDetection.xml"));

    InitDatabase();

    InitCentralWidget();

    InitStatuBar();

    InitDescription();

    InitTCPRecognizeClient();

    InitTCPPLCClient();

    _instance = this;
}

MainWindow::~MainWindow()
{
    OnClose();

    if(m_pTimer->isActive())
        m_pTimer->stop();

    if(m_pTimer != nullptr){
        delete m_pTimer;
        m_pTimer = nullptr;
    }

    if (m_pSeatParameterDialog != nullptr) {
        delete m_pSeatParameterDialog;
        m_pSeatParameterDialog = nullptr;
    }

    if (m_pDetectionDialog != nullptr) {
        delete m_pDetectionDialog;
        m_pDetectionDialog = nullptr;
    }

    sqlitedatabasedao.closeDatabase();

    if (m_pTcpPLCClient != nullptr) {
        delete m_pTcpPLCClient;
        m_pTcpPLCClient = nullptr;
    }

    if (m_pTcpRecognizeClient != nullptr) {
        delete m_pTcpRecognizeClient;
        m_pTcpRecognizeClient = nullptr;
    }


#ifdef USE_LOGGING
    UninitLog();
#endif

    delete infoLabel;

    for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
        QWidget* pWidget = m_pWidgetVideos.at(i);
        delete pWidget;

        DahengCamera* pCamera = (DahengCamera*)m_pCameras.at(i);
        delete pCamera;
    }

    delete ui;

    _instance = nullptr;
}

MainWindow* MainWindow::instance() {
    return _instance;
}

/**
 * @brief MainWindow::SelfTest
 *  参数文件的中的所有的硬件自检
 */
void MainWindow::SelfTest(){
    foreach(Camera* pCamera,m_pCameras){
        pCamera;
    }
}
//////////////////////////////////////////////////////////////////////////
/// \brief 初始化CentraWidget,包括MainWindow主窗口的不同部分。分为以下几个部分：
/// 1）最左侧的按钮区域的所有按钮
/// 2）左侧下方的LOGO区域
/// 3）中间区域，由Stack控件包含的
/// 4）List的图像列表及下方的操作按钮
/// 5）中间下方的综合区域，由Stack控件包含
/// 6）右侧多个摄像显示视频区域
/// 7）系统定时器
///
void MainWindow::InitCentralWidget()
{
    qDebug() << (QString("初始化 InitCentralWidget..."));
    //LS_INFO("你好！！！！！！！！！！！！！");
    InitButtonWidget();
    InitLogoWidget();

    // page 0
    InitMainCameraWidget();
    // page 1
    InitMainExportWidget();

    InitControlWidget();
    InitCompositeWidget();
    InitSubCameraWidget();
    InitTimerWidget();
}

void MainWindow::InitButtonWidget()
{
    ui->buttonRun->setStyleSheet(
        "QPushButton { background-color: rgb(0,0,255); color: rgb(255,255,255); }");
    connect(ui->buttonRun, &QPushButton::clicked, this, &MainWindow::ButtonRunFunction);

    ui->buttonTest->setStyleSheet(
        "QPushButton { background-color: rgb(250,140,0); color: rgb(255,255,255); }");
    connect(ui->buttonTest, &QPushButton::clicked, this, &MainWindow::ButtonTestFunction);

    connect(ui->buttonParameterConfig, &QPushButton::clicked, this, &MainWindow::ButtonParameterConfigFunction);
}

void MainWindow::InitLogoWidget() {
    // 加载图片，创建一个QPixmap对象
    QPixmap pixmap(":/res/res/image/chery.jpg"); // 替换为你的图片路径
    // 在QLabel上显示图片
    ui->labelLogo->setPixmap(pixmap);
}

void MainWindow::InitMainCameraWidget()
{
    ui->widgetMainCamera->SetFileNumber(0);
}

void MainWindow::InitMainExportWidget(){
    int imageCount = seatDetectionParameter.GetDetectionTotalSubImageCount();
    int cameraCount = seatDetectionParameter.GetCameras().size();
    QList<int> cameraPositions;
    for(int i = 0 ;i < imageCount; i++){
        cameraPositions.append(0);
    }
    //转换一下
    for(int i = 0 ;i < cameraCount; i++){
        QStringList list = seatDetectionParameter.GetCameras().at(i).numbers;
        for(int j = 0; j < list.size(); j++){
            QString pos = list.at(j);
            cameraPositions[pos.toInt() - 1] = i + 1;
        }
    }

    QList<QComboBox*> combos;
    int index = 0;
    // 偶数个图像
    if(imageCount % 2 == 0){
        QFormLayout* form = (QFormLayout*)ui->groupBoxExportSettingLeft->layout();
        // 左边一列
        for(int i = 0; i < imageCount / 2; i++){
            QComboBox* box = new QComboBox(this);
            box->addItem(QString("选择相机"));
            for (int j = 0; j < cameraCount; j++) {
                box->addItem(QString("相机%1").arg(j + 1));
            }
            combos.append(box);
            form->addRow(new QLabel(QString("图像%1").arg(i + 1)),box);
            box->setCurrentIndex(cameraPositions[index++]);
            //box->
        }
        // 右边一列
        form = (QFormLayout*)ui->groupBoxExportSettingRight->layout();
        for(int i = 0; i < imageCount / 2; i++){
            QComboBox* box = new QComboBox(this);
            box->addItem(QString("选择相机"));
            for (int j = 0; j < cameraCount; j++) {
                box->addItem(QString("相机%1").arg(j + 1));
            }
            combos.append(box);
            form->addRow(new QLabel(QString("图像%1").arg(imageCount / 2 + i + 1)),box);
            box->setCurrentIndex(cameraPositions[index++]);
        }
    }else{ // 奇数个图像
        QFormLayout* form = (QFormLayout*)ui->groupBoxExportSettingLeft->layout();
        // 左边一列
        for(int i = 0; i <= imageCount / 2; i++){
            QComboBox* box = new QComboBox(this);
            box->addItem(QString("选择相机"));
            for (int j = 0; j < cameraCount; j++) {
                box->addItem(QString("相机%1").arg(j + 1));
            }
            combos.append(box);
            form->addRow(new QLabel(QString("图像%1").arg(i + 1)),box);
            box->setCurrentIndex(cameraPositions[index++]);
        }
        form = (QFormLayout*)ui->groupBoxExportSettingRight->layout();
        // 右边一列
        for(int i = 0; i < imageCount / 2; i++){
            QComboBox* box = new QComboBox(this);
            box->addItem(QString("选择相机"));
            for (int j = 0; j < cameraCount; j++) {
                box->addItem(QString("相机%1").arg(j + 1));
            }
            combos.append(box);
            form->addRow(new QLabel(QString("图像%1").arg(imageCount / 2 + i + 1 + 1)),box);
            box->setCurrentIndex(cameraPositions[index++]);
        }
    }
}

void MainWindow::InitControlWidget()
{
    QStringList ls;
    for (int i = 0; i < seatDetectionParameter.GetDetectionTotalSubImageCount(); i++) {
        ls.append(QString("%1").arg(i + 1));
    }
    ui->listWidgetSeatPosition->addItems(ls);
    QListWidgetItem *item = ui->listWidgetSeatPosition->item(0);
    ui->listWidgetSeatPosition->setCurrentItem(item);


    // 设置所有控制按钮的暗色
    /*ui->buttonSave->setStyleSheet("QPushButton { background-color: rgb(64,64,64); color: rgb(255,255,255); }");
    ui->buttonComputeCurrent->setStyleSheet("QPushButton { background-color: rgb(64,64,64); color: rgb(255,255,255); }");
    ui->buttonComputeAll->setStyleSheet("QPushButton { background-color: rgb(64,64,64); color: rgb(255,255,255); }");
    ui->buttonSnap->setStyleSheet("QPushButton { background-color: rgb(64,64,64); color: rgb(255,255,255); }");
    ui->buttonVideo->setStyleSheet("QPushButton { background-color: rgb(64,64,64); color: rgb(255,255,255); }");*/

    // 绑定信号与槽
    connect(ui->buttonSave, &QPushButton::clicked, this, &MainWindow::ButtonSaveFunction);
    connect(ui->buttonComputeCurrent,
            &QPushButton::clicked,
            this,
            &MainWindow::ButtonComputeCurrentFunction);
    connect(ui->buttonComputeAll,
            &QPushButton::clicked,
            this,
            &MainWindow::ButtonComputeAllFunction);
    //connect(ui->buttonSnap, &QPushButton::clicked, this, &MainWindow::ButtonSnapFunction);
    //connect(ui->buttonVideo, &QPushButton::clicked, this, &MainWindow::ButtonVideoFunction);
}

void MainWindow::InitCompositeWidget()
{
    ui->listWidgetDataQuery->setViewMode(QListView::IconMode);
    ui->listWidgetDataQuery->setIconSize(QSize(128, 128));
    QIcon Icon(":/res/res/image/seat.png");

    QList<Seat*> list;

    /*pSeatDao->queryRecent(list);
    for (int i = 0; i < list.size(); i++)
    {
        Seat* pSeat = list.at(i);
        QListWidgetItem* pListItem = new QListWidgetItem(Icon, pSeat->getSeatNumber());
        ui->listWidgetDataQuery->addItem(pListItem);
    }*/
}

void MainWindow::InitSubCameraWidget()
{
    //for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++)
    foreach(CAMERA camera , seatDetectionParameter.GetCameras())
    {
        QWidget* pWidget = new QWidget(this);
        pWidget->setMinimumSize(240, 160);
        pWidget->setMaximumSize(240, 160);

        ui->groupBoxSubCamera->layout()->addWidget(pWidget);
        m_pWidgetVideos.append(pWidget);

        Camera* pCamera;
        pCamera = new DahengCamera(pWidget,camera.IP);
        QStringList numbers = camera.numbers;
        pCamera->SetMaxiumIndex(numbers.size());
        m_pCameras.append(pCamera);

        /*if(GX_STATUS_SUCCESS == pCamera->OpenDevice()){
            pCamera->ConfigCaptureVideo();
            pCamera->StartSnap();
        }*/
    }

    //启动一个子线程，帮忙打开所有的相机
    // 2024-06-23 现在不用了，采用定时器
    /*m_pScanCameraThread = new ScanCameraThread(this);
    m_pScanCameraThread->SetParam(&m_pCameras);
    m_pScanCameraThread->start();*/
}

void MainWindow::InitTimerWidget()
{
    m_pTimer = new QTimer();
    connect(m_pTimer, &QTimer::timeout, this, &MainWindow::timerTimeOut);
    m_pTimer->start(1000);
}

void MainWindow::InitTCPRecognizeClient()
{
    qDebug() << QString("创建缺陷识别TCP客户端...");
    m_pTcpRecognizeClient = new TCPRecognizeClient(this);

    connect(m_pTcpRecognizeClient,
            &TCPRecognizeClient::newResultMessage,
            this,
            &MainWindow::ReceviceComputeResultFunctionFromRecognizeService);

    qDebug() << QString("连接缺陷识别TCP服务器: %1:%2 ...")
                    .arg(seatDetectionParameter.GetRecognitionServerIp())
                    .arg(seatDetectionParameter.GetRecognitionServerPort());
    m_pTcpRecognizeClient->ConnectServer(seatDetectionParameter.GetRecognitionServerIp(),
                             seatDetectionParameter.GetRecognitionServerPort().toInt());
}

void MainWindow::InitTCPPLCClient()
{
    qDebug() << QString("创建PLC控制TCP客户端...");
    m_pTcpPLCClient = new TCPPLCClient(this);

    /*connect(tcpClientPLC,
            &TCPClient::newResultMessage,
            this,
            &MainWindow::RecviceControlCmdFunctionFromService);*/

    connect(m_pTcpPLCClient,
            &TCPPLCClient::newSeatMessage,
            this,
            &MainWindow::ReceiveControlCmdFunctionFromPLCService);

    qDebug() << QString("连接PLC控制TCP服务器: %1:%2 ...")
                    .arg(seatDetectionParameter.GetControlServerIp())
                    .arg(seatDetectionParameter.GetControlServerPort());
    m_pTcpPLCClient->ConnectServer(seatDetectionParameter.GetControlServerIp(),
                                seatDetectionParameter.GetControlServerPort().toInt());
}

void MainWindow::InitLog()
{
    SaveLog::Instance()->setPath(qApp->applicationDirPath() + "/logs");
    SaveLog::Instance()->start();
}

void MainWindow::UninitLog()
{
    SaveLog::Instance()->stop();
}

void MainWindow::InitParameterFromXMLFile(QString xmlFilePath)
{
    qDebug() << QString("初始化参数...");
    seatDetectionParameter.InitParameter();
    qDebug() << QString("初始化参数文件: %1...").arg(xmlFilePath);
    seatDetectionParameter.ReadParameterFromXml(xmlFilePath);
}

void MainWindow::InitDatabase()
{
    qInfo() << QString("初始化并连接数据库 ...");
    sqlitedatabasedao.connectDatabase();
    qInfo() << QString("打开数据库 ...");
    sqlitedatabasedao.openDatabase();
    qInfo() << QString("初始化数据库表 ...");
    sqlitedatabasedao.createDatabaseTable();

    qInfo() << QString("实例化数据库访问接口层对象（DAO） ...");
    pSeatDao = new SeatDao();
    pDetectionDao = new DetectionDao();
    pDefectDao = new DefectDao();
}

void MainWindow::InitStatuBar(){
    qInfo() << QString("初始化状态栏 ...");
    infoLabel = new QLabel(this);
    //perLabel->setFrameStyle(QFrame::Box | QFrame::Sunken);
    infoLabel->setText(QString("检测座椅数量：%1").arg(100));
    infoLabel->setTextFormat(Qt::RichText);
    ui->statusbar->addPermanentWidget(infoLabel);

    this->UpdateStatusBarInfo();
}
/**
 * @brief MainWindow::InitDescription
 * 初始化Description
 */
void MainWindow::InitDescription(){
    // objectFactory init
    qInfo() << QString("初始化Description ...");
    m_descriptionThread = new DescriptionThread();
    m_descriptionThread->SetSeatDetectionParameter(&seatDetectionParameter);
    m_descriptionThread->SetXMLFilePath(seatDetectionParameter.getDescriptionFilePath());
    connect(m_descriptionThread,&DescriptionThread::SendCommandToMainWindow,
            this,&MainWindow::ProcessImageFromDescription);
    m_descriptionThread->start();

    /*ObjectFactory::registerClass<Delay>();
    ObjectFactory::registerClass<WordopControlLED>();
    ObjectFactory::registerClass<MoveJoint>();
    ObjectFactory::registerClass<RS232>();
    ObjectFactory::registerClass<Ethernet>();
    ObjectFactory::registerClass<JakaRobot>();
    ObjectFactory::registerClass<AuboRobot>();
    ObjectFactory::registerClass<VirtualDevice>();
    ObjectFactory::registerClass<Step>();
    ObjectFactory::registerClass<Snap>();
    ObjectFactory::registerClass<Recognize>();

    qInfo() << QString("从描述文件中加载Description ...");
    m_description.clear();
    //m_description.ReadXML("d:/description.xml");
    m_description.ReadXML(seatDetectionParameter.getDescriptionFilePath());
    //m_description.initAllDevices();
    // 初始化线程，开始初始化
    DescriptionInitThread* pDescriptionInitThread = new DescriptionInitThread(this);
    pDescriptionInitThread->SetDevices(m_description.GetDevices());
    pDescriptionInitThread->start();
    // 设置所有设备初始状态标志，避免重复被初始化
    m_description.SetAllInitialized(true);

    connect(&m_description,&Description::SendCmdToMainWindow,this,&MainWindow::ProcessImageFromDescription);
    */
}

void MainWindow::ScanCameras(){
    foreach (Camera* pCamera, m_pCameras) {
        if(!pCamera->IsOpen()){
            if(GX_STATUS_SUCCESS == pCamera->OpenDevice()){                
                pCamera->ConfigCaptureVideo();
                pCamera->InitDevice();
                pCamera->StartSnap();
            }else{
                m_bHasSomeClosed = true;
            }
        }
    }
}

void MainWindow::DisplaySystemTime()
{
    QString strTime = QDateTime::currentDateTime().toString("yyyy年MM月dd日 hh时mm分ss秒");
    ui->labelSystemTime->setText(strTime);
}

void MainWindow::timerTimeOut(){
    // 显示系统时间
    DisplaySystemTime();
    // 按照一定的周期，扫描摄像机
    ScanCameras();
}

// (1) 核心函数
void MainWindow::ButtonRunFunction()
{
    qInfo() << QString("开始实时检测 ...");
    qInfo() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    // 开始实时显示对话框
    if(m_pDetectionDialog != nullptr){
        // 先清除上一次的
        delete m_pDetectionDialog;
        m_pDetectionDialog = nullptr;
    }

    m_pDetectionDialog = new DetectionDialog(seatDetectionParameter, this);
    m_pDetectionDialog->setStyleSheet("QDialog { background-color: rgb(50,75,100); }");
    connect(m_pDetectionDialog, &DetectionDialog::sendButtonControlCmd, this, &MainWindow::RecviceControlCmdFunctionFromDialog);
    connect(this, &MainWindow::SendLogMessageToTextBrowser, m_pDetectionDialog,&DetectionDialog::ReceiveLogMessage);
    connect(this, &MainWindow::ClearDetectionDialogImage,m_pDetectionDialog,&DetectionDialog::ClearImage);
    connect(this,&MainWindow::SendHistoryInformation,m_pDetectionDialog,&DetectionDialog::ReceiveNewHistoryInforamtion);
    connect(m_pDetectionDialog, &DetectionDialog::sendQuerySeat, this, &MainWindow::RecviceQuerySeatFromDialog);
    // 全屏显示
    qInfo() << QString("开始显示DetectionDialog ...");
    //pDetectionDialog->showFullScreen();
    //m_pDetectionDialog->showMaximized();
    // 模态显示
    //qDebug() << "收到几个结果：" << m_DetectionResults.size();
    m_pDetectionDialog->show();

    // 显示对话框打开前接收到的结果
    foreach (DetectionResult* pDR, m_DetectionResults) {
        m_pDetectionDialog->SetDetectionResult(seatDetectionParameter, *pDR, true);
    }
    // 查最近的五条记录，在DetetionDialog的历史表格中显示
    qDebug() << "查最近的五条记录，在DetetionDialog的历史表格中显示";
    QueryRecentSeat();
}
/**
 * @brief MainWindow::ButtonTestFunction
 * 进入测试页
 */
void MainWindow::ButtonTestFunction()
{
    qInfo() << QString("开始实时测试 ...");
    ui->stackedWidget->setCurrentIndex(0);
}
/**
 * @brief MainWindow::on_pushButtonExportSetting_clicked
 * 进入出口设置页
 */
void MainWindow::on_pushButtonExportSetting_clicked()
{
    //ui->stackedWidget->setCurrentIndex(1);

    //ScanCameraThread* pThread = new ScanCameraThread(this);
    //pThread->start();
}
/**
 * @brief MainWindow::on_pushButtonResetStatistics_clicked
 * 重置统计
 */
void MainWindow::on_pushButtonResetStatistics_clicked()
{
    m_nTrayCount = 0;
    m_nSeatCount = 0;
    m_nDetectionCount = 0;
    m_nDefectSeatCount = 0;
    m_nDefectCount = 0;
    UpdateStatusBarInfo();
}
/**
 * @brief MainWindow::on_pushButtonHelp_clicked
 * 帮助
 */
void MainWindow::on_pushButtonHelp_clicked()
{
    QMessageBox::about(nullptr, "关于座椅缺陷检测软件",
                       "<h2>座椅缺陷检测软件</h2>"
                       "<p>Version 1.0</p>"
                       "<p>版权所有 © 2024 HIT </p>");
}


/**
 *  弹出主要参数配置对话框，参数保存到xml格式的参数文件中
 */
void MainWindow::ButtonParameterConfigFunction()
{
    m_pSeatParameterDialog = new SeatParameterDialog(seatDetectionParameter, this);
    m_pSeatParameterDialog->setWindowTitle(QStringLiteral("参数配置"));
    int rect = m_pSeatParameterDialog->exec();
    if (rect == QDialog::Accepted) {
        seatDetectionParameter.WriteParameterToXml("seatdetection.xml");
    }
}

void MainWindow::UpdateStatusBarInfo(){
    infoLabel->setText(QString("托盘:%1个; 座椅:%2个; 检测图像:%3张; 缺陷座椅:%4个; 缺陷:%5个")
                       .arg(m_nTrayCount).arg(m_nSeatCount).arg(m_nDetectionCount)
                           .arg(m_nDefectSeatCount).arg(m_nDefectCount));
}

/**
 * @brief 保存当前图像到指定的文件夹中
 */
void MainWindow::ButtonSaveFunction()
{
    qInfo() << QString("开始保存图像 ...");
    QString fileName = QFileDialog::getSaveFileName(this, "保存文件", "", "JPEG Files (*.jpg)");
    if (!fileName.isEmpty()) {
        // save contents to the selected file
    }
}

/**
 * @brief 计算当前抓拍到的图像
 */
void MainWindow::ButtonComputeCurrentFunction()
{
    qInfo() << QString("开始计算当前图像的缺陷 ...");
    controlCommand.SetCmd(QStringLiteral("predict"));
    controlCommand.SetSeatNumber(currentSeat.getSeatNumber());

    QList<QListWidgetItem *> items = ui->listWidgetSeatPosition->selectedItems();
    if (items.size() > 0) {
        controlCommand.SetFileName(items[0]->text());
        // 构造为JSON串，并发送给处理服务器
        QString jsonStr = controlCommand.toJson();
        m_pTcpRecognizeClient->sendRawMessage(jsonStr);
    }
}

/**
 * @brief MainWindow::ButtonComputeAllFunction
 */
void MainWindow::ButtonComputeAllFunction()
{
    qInfo() << QString("开始计算所有图像的缺陷 ...");
    ControlCommand controlCommand;
    controlCommand.SetCmd(QStringLiteral("predict"));
    controlCommand.SetSeatNumber(QStringLiteral("12345678"));

    int itemsCount = ui->listWidgetSeatPosition->count();
    for (int i = 0; i < itemsCount; i++) {
        QListWidgetItem *item = ui->listWidgetSeatPosition->item(i);
        controlCommand.SetFileName(item->text());

        QString jsonStr = controlCommand.toJson();
        m_pTcpRecognizeClient->sendRawMessage(jsonStr);
    }
}

// 抓拍图像
void MainWindow::SnapImageFunction(QString deviceIP,QString image)
{
    qDebug() << QString("开始抓拍一张图像... %1:%2").arg(deviceIP).arg(image);
    //LS_INFO("Hello World! "<< 12345);
    //SnapCameraImage(0);
    CAMERA camera;
    bool isCameraFound = false;

    foreach(camera, seatDetectionParameter.GetCameras()){
        QStringList ImageNumbers = camera.numbers;
        if(deviceIP == camera.IP){
            isCameraFound = true;
            break;
        }
    }

    if(isCameraFound){
        for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
            Camera* pCamera = m_pCameras.at(i);
            // 根据IP找到相机对象
            if(camera.IP == pCamera->GetIP()){
                if(pCamera->IsOpen() && pCamera->IsSnap()){
                    pCamera->TriggerSoftware();

                    QString strPathName = QString("%1/%2.bmp")
                                              .arg(seatDetectionParameter.GetOriginalImagePath())
                                              .arg(image);

                    qDebug() << strPathName;
                    pCamera->SaveBmp(strPathName.toLatin1().data());
                }
            }
        }
    }
}

// 视频
void MainWindow::ButtonVideoFunction()
{
    qDebug() << QString("开始视频显示...");
}
//////////////////////////////////////////////////////
/// \brief MainWindow::SnapCameraImage
/// \param cameraNum 相机编号
///
void MainWindow::SnapCameraImage(int cameraNum){
    QStringList ImageNumbers = seatDetectionParameter.GetCameras().at(cameraNum).numbers;
    Camera* pCamera = m_pCameras.at(cameraNum);
    QString filename = ImageNumbers[pCamera->GetIndex()];
    pCamera->IncIndex();
    QString strPathName = QString("%1/%2.bmp")
                              .arg(seatDetectionParameter.GetOriginalImagePath())
                              .arg(filename);

    qDebug() << strPathName;

    pCamera->SaveBmp(strPathName.toLatin1().data());
}

/**
 * (1) 接收从PLC服务器发送的信息，包括座椅相关信息，从而启动测试流程
 * @brief MainWindow::ReceiveControlCmdFunctionFromPLCService
 * @param trayNumber : 托盘编号
 * @param seatNumber : 座椅编号
 * @param direction  : 是汽车左侧还是右侧座椅
 */
void MainWindow::ReceiveControlCmdFunctionFromPLCService(QString trayNumber,
                                                         QString seatNumber,
                                                         QString direction){
    qDebug() << QString("接收到PLC服务器数据 : %1,%2,%3").arg(trayNumber).arg(seatNumber).arg(direction);
    //emit SendPLCControlMessage(seatNumber);
    currentSeat.setSeatDirection(direction);
    currentSeat.setTrayNumber(trayNumber);
    currentSeat.setSeatNumber(seatNumber);
    currentSeat.setNote("");
    // 保存座椅信息到数据库中
    m_nLastSeatId = pSeatDao->insert(currentSeat);
    // 创建一个目录
    QString dirPath = seatDetectionParameter.GetOriginalImagePath() + "/" + currentSeat.getSeatNumber();
    QDir dir;
    if(!dir.exists(dirPath)){
        bool success = dir.mkdir(dirPath);
        if(success){

        }
    }

    ///////////////////////////////////////////////////////////////
    // 通知DetectionDialog清除所有的上一次的图片
    emit ClearDetectionDialogImage();
    // 清除所有处理结果
    ClearDetetionResults();

    // 修改统计数据
    m_nTrayCount++;
    m_nSeatCount++;
    // 开始运行测试流程
    //m_description.run();

    m_descriptionThread->SetRunnable(true);
    m_descriptionThread->start();
}

/**
 * (2) 接收从测试流程发送的信息，包括座椅抓拍图像指令或识别图像指令
 * @brief MainWindow::ProcessImageFromDescription 接收到从Description转发的抓拍图像或识别
 * @param variant 是一个Map，其中，键值classname对应发送指令的类名；键值content对应发送指令的图像编号
 */
void MainWindow::ProcessImageFromDescription(QVariant variant){
    const QMap<QString,QVariant> map = variant.toMap();
    QVariant strClassName = map["classname"];
    QVariant strImageNumber = map["content"];
    int imageNumber = strImageNumber.toInt();

    qDebug() << "Caputre a Image : " << strClassName << strImageNumber;

    CAMERA camera;
    bool isCameraFound = false;

    foreach(camera, seatDetectionParameter.GetCameras()){
        QStringList ImageNumbers = camera.numbers;
        if(ImageNumbers.contains(QString::number(imageNumber))){
            isCameraFound = true;
            break;
        }
    }

    if(isCameraFound){
        if(strClassName == "Snap"){ // 如果是Snap发来的指令
            qDebug() << QString("接收到抓拍图像指令: %1 。").arg(imageNumber);
            emit SendLogMessageToTextBrowser(QString("接收到抓拍图像指令: %1 。").arg(imageNumber));

            for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
                Camera* pCamera = m_pCameras.at(i);
                // 根据IP找到相机对象
                if(camera.IP == pCamera->GetIP()){
                    if(pCamera->IsOpen() && pCamera->IsSnap()){
                        pCamera->TriggerSoftware();
                        // 构建图像名称
                        QString strPathName = seatDetectionParameter.GetOriginalImagePath()
                                              + "/" + currentSeat.getSeatNumber()
                                              + "/" + QString::number(imageNumber)
                                              + "." + seatDetectionParameter.getImageFileExtension();

                        qDebug() << strPathName;
                        QByteArray ba = strPathName.toLatin1();
                        // 保存图像
                        if(seatDetectionParameter.getImageFileExtension() == "bmp"){
                            pCamera->SaveBmp(ba.data());
                        }else if(seatDetectionParameter.getImageFileExtension() == "jpg"){
                            pCamera->SaveJpeg(ba.data());
                        }else{
                            //pCamera->SaveJpeg(ba.data());
                        }

                    }
                }
            }
        }else{ // 如果是Recognize发来的指令
            qDebug() << QString("接收到识别图像指令: %1 。").arg(imageNumber);
            emit SendLogMessageToTextBrowser(QString("接收到识别图像指令: %1 。").arg(imageNumber));

            controlCommand.SetCmd(QStringLiteral("predict")); // 该指令让缺陷识别服务器识别处理
            controlCommand.SetSeatNumber(currentSeat.getSeatNumber()); // 已获知座椅标号
            controlCommand.SetFileName(QString::number(imageNumber));
            // 组合为JSON字符串，通知
            QString jsonStr = controlCommand.toJson();
            m_pTcpRecognizeClient->sendRawMessage(jsonStr);
            qDebug() << QString("发送预测指令：%1 。").arg(jsonStr);
            emit SendLogMessageToTextBrowser(QString("发送预测指令：%1 。").arg(jsonStr));

            m_nDetectionCount++;
            //更新状态信息内容
            UpdateStatusBarInfo();
        }
    }
}

/**
 * (3) 接收从识别处理服务器接收到结果信息
 * @brief MainWindow::ReceviceComputeResultFunctionFromRecognizeService
 * @param resultJson
 */
void MainWindow::ReceviceComputeResultFunctionFromRecognizeService(QString resultJson){
    QStringList list = resultJson.split("}{");

    QString str_;
    for(int i = 0;i < list.size() ; i++){
        str_ = list[i];
        if(i != 0){
            str_ = "{" + str_;
        }

        if(i != list.size() - 1){
            str_ = str_ + "}";
        }

        ProcessOneComputeResultFunctionFromRecognizeService(str_);
    }
}

/**
 * @brief MainWindow::ProcessOneComputeResultFunctionFromRecognizeService
 * 处理一个结果
 * @param resultJson
 */
void MainWindow::ProcessOneComputeResultFunctionFromRecognizeService(QString resultJson)
{
    qDebug() << QString("接收到缺陷识别服务器数据: %1").arg(resultJson);
    emit SendLogMessageToTextBrowser(QString("接收到缺陷识别服务器数据: %1").arg(resultJson));
    // 解析获得的json字符串（处理结果）
    DetectionResult* pDetectionResult = new DetectionResult();
    pDetectionResult->fromJson(resultJson);
    m_DetectionResults.append(pDetectionResult);

    // 当收到一个座椅的所有图像的检测结果
    if(m_DetectionResults.size() == seatDetectionParameter.GetDetectionTotalSubImageCount()){
        HISTORYINFORMATION* pHI = new HISTORYINFORMATION();
        ComputeHistoryInformation(*pHI);
        m_HistoryInformations.prepend(pHI);
        emit SendHistoryInformation(m_HistoryInformations);
    }

    detectionResult.fromJson(resultJson);
    // 给图像显示窗口显示图片
    // 是不是消息传递更好
    ui->widgetMainCamera->SetDetectionResult(seatDetectionParameter, detectionResult,false);
    // 将结果送检测对话框显示
    if (m_pDetectionDialog != nullptr) {
        m_pDetectionDialog->SetDetectionResult(seatDetectionParameter, detectionResult,true);
    }
    // 准备保存信息到数据库中
    // 获取图像处理服务器返回的座椅编号
    Detection detection(0,
                        m_nLastSeatId,
                        detectionResult.GetInfo().GetFileName(),
                        QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"),
                        QStringLiteral(""));

    int nLastDetectionId = pDetectionDao->insert(detection);
    qDebug() << QString("保存检测信息到数据库中，检测记录 id 是: %1").arg(nLastDetectionId);
    //int detectionid,QString type,QRectF range,QString note
    QList<DefectInfo> &defectInfos = detectionResult.GetResult();
    foreach (DefectInfo detectInfo, defectInfos) {
        Defect defect(0, nLastDetectionId, detectInfo.GetType(), detectInfo.GetRange(), "");
        int nLastDefectId = pDefectDao->insert(defect);
        qDebug() << QString("保存检测信息到数据库中，缺陷记录 id 是: %1 。").arg(nLastDefectId);
    }
    // 更新缺陷统计信息
    if(defectInfos.size() > 0){
        m_nDefectSeatCount++;
        m_nDefectCount += defectInfos.size();
    }
}

// 从PLC控制处理服务器接收到结果信息，
/**
 * @brief 处理从PLC控制服务器发送的指令
 * @param content : josn字符串，里面带着指令，内容
 */
/*
void MainWindow::RecviceControlCmdFunctionFromService(QString content)
{
    qDebug() << QString("接收到PLC服务器数据: %1 。").arg(content);
    emit SendLogMessageToTextBrowser(QString("接收到PLC服务器数据: %1 。").arg(content));

    plccontrolcmd.FromJson(content);
    if (plccontrolcmd.GetCmd() == QStringLiteral("tray")) { // 托盘编号
        currentSeat.setTrayNumber(plccontrolcmd.GetContent());
        ///////////////////////////////////////////////////////////////
        // 通知DetectionDialog清除所有的上一次的图片
        emit ClearDetectionDialogImage();

        m_nTrayCount++;
    } else if (plccontrolcmd.GetCmd() == QStringLiteral("seat")) { // 座椅编号
        currentSeat.setSeatNumber(plccontrolcmd.GetContent());
        m_nSeatCount++;
    } else if (plccontrolcmd.GetCmd() == QStringLiteral("direction")) { // 方向：左侧，右侧
        currentSeat.setSeatDirection(plccontrolcmd.GetContent());
    } else if (plccontrolcmd.GetCmd()
               == QStringLiteral("position")) { // 采集到该位置的图片，通知缺陷识别服务器处理
        controlCommand.SetCmd(QStringLiteral("predict")); // 该指令让缺陷识别服务器识别处理
        controlCommand.SetSeatNumber(currentSeat.getSeatNumber()); // 已获知座椅标号
        controlCommand.SetFileName(plccontrolcmd.GetContent());
        // 组合为JSON字符串，通知
        QString jsonStr = controlCommand.toJson();
        tcpClient->sendRawMessage(jsonStr);
        qDebug() << QString("发送预测指令：%1 。").arg(jsonStr);
        emit SendLogMessageToTextBrowser(QString("发送预测指令：%1 。").arg(jsonStr));

        // 利用匹配器检测当前座椅与前一个座椅是否改变
        if (seatMatcher.isChange(currentSeat, previousSeat, MATCHERMODE::SEAT)) {
            // 若改变，保存数据
            previousSeat = currentSeat;
            // 若改变，保存数据到数据库中
            currentSeat.setNote("");
            nLastSeatId = pSeatDao->insert(currentSeat);
        }

        m_nDetectionCount++;
    }
    //更新状态信息内容
    UpdateStatusBarInfo();
}
*/


/**
 * 金：确认一下这个函数的作用
 * @brief MainWindow::RecviceControlCmdFunctionFromDialog
 * @param content
 */
void MainWindow::RecviceControlCmdFunctionFromDialog(QString content)
{
    qDebug() << content;
    if(content == "CloseDialog"){
        // 如果用户关闭了DetectionDialog对话框,清除该对话框对象所占据的资源
        disconnect(m_pDetectionDialog, &DetectionDialog::sendButtonControlCmd, this, &MainWindow::RecviceControlCmdFunctionFromDialog);
        disconnect(this, &MainWindow::SendLogMessageToTextBrowser, m_pDetectionDialog,&DetectionDialog::ReceiveLogMessage);
        disconnect(this, &MainWindow::ClearDetectionDialogImage,m_pDetectionDialog,&DetectionDialog::ClearImage);
        disconnect(this,&MainWindow::SendHistoryInformation,m_pDetectionDialog,&DetectionDialog::ReceiveNewHistoryInforamtion);
        disconnect(m_pDetectionDialog, &DetectionDialog::sendQuerySeat, this, &MainWindow::RecviceQuerySeatFromDialog);

        delete m_pDetectionDialog;
        m_pDetectionDialog = nullptr;
    }else{
        m_pTcpPLCClient->sendRawMessage(content);
    }
}

/**
 * @brief MainWindow::QueryRecentSeat
 * 在数据库中查最近的五条记录
 * @param howMuch
 */
void MainWindow::QueryRecentSeat(int howMuch){
    // 先清除上一次的
    if(m_HistoryInformations.size() > 0){
        foreach (HISTORYINFORMATION* pHI, m_HistoryInformations) {
            delete pHI;
        }

        m_HistoryInformations.clear();
    }

    qDebug()<<"m_DetectionResultsForQuery's Size is :" << m_DetectionResultsForQuery.size();

    // 再重新查询并装配
    int countDefect;
    QString detectionDate = "";
    QList<Seat*> seats;
    int count = pSeatDao->queryRecent(seats,howMuch);
    //qDebug()<<"seats's is :" << seats.size();
    if(seats.size() > 0){
        foreach (Seat* pSeat, seats) {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
            countDefect = 0;
            HISTORYINFORMATION* pHI = new HISTORYINFORMATION();
            QList<Detection*> detections;
            pDetectionDao->queryBySeatId(detections,pSeat->getId());

            if(detections.size() > 0){
                foreach (Detection* pDetection, detections) {
                    DetectionResult* pDetectionResult = new DetectionResult();
                    ControlCommand* pControlCommand = new ControlCommand();
                    pControlCommand->SetCmd("predict");
                    pControlCommand->SetFileName(pDetection->getPosition());
                    pControlCommand->SetSeatNumber(pSeat->getSeatNumber());

                    QList<Defect*> defects;
                    pDefectDao->queryByDetectionId(defects,pDetection->getId());
                    if(defects.size() > 0){
                        foreach (Defect* pDefect, defects) {
                            DefectInfo* pdi = new DefectInfo();
                            pdi->SetType(pDefect->getType());
                            pdi->SetRange(pDefect->getRect());
                            pDetectionResult->AppendDefectInfo(*pdi);
                            pDetectionResult->SetInfo(*pControlCommand);
                        }
                    }
                    detectionDate = pDetection->getDetectTime();
                    countDefect += defects.size();

                    m_DetectionResultsForQuery.append(pDetectionResult);
                }
            }
            pHI->seatNumber = pSeat->getSeatNumber();
            pHI->defectCount = countDefect;
            pHI->detectionDate = detectionDate;
            m_HistoryInformations.prepend(pHI);
        }
    }
    emit SendHistoryInformation(m_HistoryInformations);
}

void MainWindow::RecviceQuerySeatFromDialog(QString seatNumber){
    // 先清除上一次的
    if(m_DetectionResultsForQuery.size() > 0){
        foreach (DetectionResult* pDR, m_DetectionResultsForQuery) {
            delete pDR;
        }

        m_DetectionResultsForQuery.clear();
    }
    // 再重新查询并装配
    QList<Seat*> seats;
    int count = pSeatDao->querySeatBySeatNumber(seats,seatNumber);
    if(seats.size() > 0){
        foreach (Seat* pSeat, seats) {
            QList<Detection*> detections;
            pDetectionDao->queryBySeatId(detections,pSeat->getId());

            if(detections.size() > 0){
                foreach (Detection* pDetection, detections) {
                    DetectionResult* pDetectionResult = new DetectionResult();
                    ControlCommand* pControlCommand = new ControlCommand();
                    pControlCommand->SetCmd("predict");
                    pControlCommand->SetFileName(pDetection->getPosition());
                    pControlCommand->SetSeatNumber(pSeat->getSeatNumber());

                    QList<Defect*> defects;
                    pDefectDao->queryByDetectionId(defects,pDetection->getId());
                    if(defects.size() > 0){
                        foreach (Defect* pDefect, defects) {
                            DefectInfo* pdi = new DefectInfo();
                            pdi->SetType(pDefect->getType());
                            pdi->SetRange(pDefect->getRect());
                            pDetectionResult->AppendDefectInfo(*pdi);
                            pDetectionResult->SetInfo(*pControlCommand);
                        }
                    }

                    m_DetectionResultsForQuery.append(pDetectionResult);
                }
            }
        }
    }

    // 显示对话框查询到的结果
    foreach (DetectionResult* pDR, m_DetectionResultsForQuery) {
        m_pDetectionDialog->SetDetectionResult(seatDetectionParameter, *pDR, true);
    }
}

/**
 * @brief MainWindow::on_pushButtonDataQuery_clicked
 * 数据查询
 */
void MainWindow::on_pushButtonDataQuery_clicked()
{
}

void MainWindow::resizeEvent(QResizeEvent *event){
    ui->listWidgetDataQuery->clear();

    InitCompositeWidget();
}
////////////////////////////////////////////////////////////////
/// \brief MainWindow::InitCamera
///
///
void MainWindow::OnClose(){
    //m_description.stop();

    for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
        Camera* pCamera = m_pCameras.at(i);
        if(pCamera->IsSnap())
            pCamera->StopSnap();
        if(pCamera->IsOpen())
            pCamera->CloseDevice();
    }
    // 关闭设备库
    GXCloseLib();
}

void MainWindow::InitCameraLib(){
    //初始化库
    emStatus = GXInitLib();
    if (emStatus != GX_STATUS_SUCCESS)
    {
        qDebug()<<"初始化相机驱动库失败!";
        return ;
    }
    qDebug()<<"初始化相机驱动库成功!";
}

void MainWindow::on_pushButtonDetectionDescription_clicked()
{
    QProcess::startDetached("DetectionDescription.exe");
}

void MainWindow::on_pushButtonIndexAnalysis_clicked()
{
    SelfCheckingThread* pThread = new SelfCheckingThread(this);
    pThread->start();
}

void MainWindow::on_buttonSnap_clicked()
{
    //QModelIndex index = ui->listWidgetSeatPosition->currentIndex();
    QListWidgetItem* item = ui->listWidgetSeatPosition->currentItem();
    qDebug() << "on_buttonSnap_clicked";
    QString filename = item->text();

    CAMERA camera;
    bool isCameraFound = false;

    foreach(camera, seatDetectionParameter.GetCameras()){
        QStringList ImageNumbers = camera.numbers;
        if(ImageNumbers.contains(item->text())){
            isCameraFound = true;
            break;
        }
    }

    if(isCameraFound){
        for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
            Camera* pCamera = m_pCameras.at(i);
            // 根据IP找到相机对象
            if(camera.IP == pCamera->GetIP()){
                if(pCamera->IsOpen() && pCamera->IsSnap()){
                    pCamera->TriggerSoftware();

                    QString strPathName = QString("%1/%2.bmp")
                                              .arg(seatDetectionParameter.GetOriginalImagePath())
                                              .arg(filename);

                    qDebug() << strPathName;
                    pCamera->SaveBmp(strPathName.toLatin1().data());
                }
            }
        }
    }
}

void MainWindow::on_buttonVideo_clicked()
{
    qDebug() << "on_buttonVideo_clicked";

    for(int i = 0;i < seatDetectionParameter.GetCameras().size();i++){
        Camera* pCamera = m_pCameras.at(i);
        if(pCamera->IsOpen() && pCamera->IsSnap()){
            pCamera->CaptureVideo();
        }
    }
}

